using System.Collections;
using System.Collections.Generic;
using System.IO;
using HybridCLR.Editor;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;

public class HyEditor
{
    [MenuItem("Tools/List Player Assemblies in Console")]
    public static void PrintAssemblyNames()
    {
        UnityEngine.Debug.Log("== Player Assemblies ==");
        Assembly[] playerAssemblies =
            CompilationPipeline.GetAssemblies(AssembliesType.Player);

        foreach (var assembly in playerAssemblies)
        {
            UnityEngine.Debug.Log(assembly.name);
        }
    }

    private static UploadConfig _config;

    static void LoadConfig()
    {
        _config = AssetDatabase.LoadAssetAtPath<UploadConfig>("Assets/Editor/UploadConfig.asset");
    }

    private static List<string> hotdlls
    {
        get { return SettingsUtil.HotUpdateAssemblyNamesExcludePreserved; }
    }

    private static string targetPath
    {
        get { return _config.targetPath; }
    }

    [MenuItem("Tools/Build_Dll")]
    private static void UpLoadDll_V2()
    {
        HybridCLR.Editor.Commands.CompileDllCommand.CompileDllActiveBuildTarget();

        LoadConfig();
        var prefab_path = _config.PreLoadDll_path;
        var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefab_path);
        GameObject prefabInstance = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
        var code = prefabInstance.GetComponent<PreLoadDll>();
        code.dlls.Clear();
        code.aotdlls.Clear();
        BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
        string srcDllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
        foreach (var hotdll in hotdlls)
        {
            var filePath = $"{srcDllDir}/{hotdll}.dll";
            if (File.Exists(filePath))
            {
                var bytes = File.ReadAllBytes(filePath);
                code.dlls.Add(new DllDepend()
                {
                    name = hotdll,
                    bytes = bytes,
                    length = bytes.Length
                });
            }
        }

        Debug.Log($"Updata hot Dll finished!!! {code.dlls.Count}");

        string srcDir_aot = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
        foreach (var item in AOTGenericReferences.PatchedAOTAssemblyList)
        {
            var dllName = item.Replace(".dll", "");
            var filePath = $"{srcDir_aot}/{dllName}.dll";
            if (File.Exists(filePath))
            {
                var bytes = File.ReadAllBytes(filePath);
                code.aotdlls.Add(new DllDepend()
                {
                    name = dllName,
                    bytes = bytes,
                    length = bytes.Length
                });
            }
        }

        Debug.Log($"Updata aot Dll finished!!! {code.aotdlls.Count}");

        PrefabUtility.SaveAsPrefabAsset(prefabInstance, prefab_path);
        GameObject.DestroyImmediate(prefabInstance);
        AssetDatabase.Refresh();
        Buid();
    }


    [MenuItem("Tools/build AB")]
    static void Buid()
    {
        LoadConfig();
        List<AssetBundleBuild> builds = Search();
        BuildPipeline.BuildAssetBundles(outputPath(), builds.ToArray(),
            BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);

        var files = Directory.GetFiles(outputPath(), $"*.{ex}", SearchOption.AllDirectories);

        foreach (var file in files)
        {
            var nfile = file.Replace(@"\", "/");
            var dfile = nfile.Replace($"{outputPath()}", targetPath);
            var dir = Path.GetDirectoryName(dfile);
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
            File.Copy(nfile, dfile, true);


            var dfile2 = nfile.Replace($"{outputPath()}", Application.streamingAssetsPath);
            dir = Path.GetDirectoryName(dfile2);
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
            AssetDatabase.Refresh();
            File.Copy(nfile, dfile2, true);
        }

        AssetDatabase.Refresh();
        Debug.Log("Ab build finished!!!");
    }

    static List<AssetBundleBuild> Search()
    {
        List<AssetBundleBuild> builds = new List<AssetBundleBuild>();
        foreach (var result in _config.ab_search)
        {
            var models = AssetDatabase.FindAssets(result, new[] { "Assets/HotRes/" });

            foreach (var guid in models)
            {
                string assetPath = AssetDatabase.GUIDToAssetPath(guid);
                var arr = assetPath.Split("/");
                var fname = arr[arr.Length - 1];
                var name = fname.Split(".")[0];
                var abPath = assetPath.Replace("Assets/", "");
                abPath = abPath.Replace(fname, $"{name}.{ex}");
                // Debug.Log($"{assetPath},{fname},{name}");
                builds.Add(new AssetBundleBuild()
                {
                    assetBundleName = abPath,
                    assetNames = new string[] { assetPath }
                });
            }
        }

        return builds;
    }

    private static string ex = "unity3d";

    private static AssetBundleBuild SetAssetbundleName(string resName, string dir = "", string resex = "unity")
    {
        string path = $"Assets/HotRes/{resName}.{resex}";
        string assetBundleName = $"HotRes/{resName}.{ex}";
        if (!string.IsNullOrEmpty(dir))
        {
            path = $"Assets/HotRes/{dir}/{resName}.{resex}";
            assetBundleName = $"HotRes/{dir}/{resName}.{ex}";
        }

        AssetImporter importer = AssetImporter.GetAtPath(path);
        return new AssetBundleBuild()
        {
            assetBundleName = assetBundleName,
            assetNames = new string[] { importer.assetPath }
        };
    }

    private static string outputPath()
    {
        Caching.ClearCache();
        string outputPath = Application.dataPath.Replace("Assets", $"AssetsBundle/{PlatformName}");
        if (!Directory.Exists(outputPath))
            Directory.CreateDirectory(outputPath);
        return outputPath;
    }

    public static string PlatformName
    {
        get
        {
            string str = "def";
            switch (EditorUserBuildSettings.activeBuildTarget)
            {
                case BuildTarget.StandaloneWindows64:
                case BuildTarget.StandaloneWindows:
                    str = "Win";
                    break;
                case BuildTarget.WebGL:
                    str = "WebGL";
                    break;
            }

            return str;
        }
    }
}